<template>
    <div class="info">
        <div class="info-seach">
            <el-form label-width="100px" class="info-seach-form">
                <el-form-item label="操作事件">
                    <el-input size="mini" style="width:100%" v-model="queryForm.operateRemark" />
                </el-form-item>
                <el-form-item label="操作类型">
                    <el-select size="mini" style="width:100%" clearable v-model="queryForm.operateTypes" multiple collapse-tags>
                        <el-option v-for="(value, key) in operateTypePojo" :key="key" :label="value" :value="key"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="异常场景">
                    <el-select size="mini" style="width:100%" clearable v-model="queryForm.sceneTypes" multiple collapse-tags>
                        <el-option v-for="(value, key) in sceneTypePojo" :key="key" :label="value" :value="key"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="异常模块">
                    <el-select size="mini" style="width:100%" clearable v-model="queryForm.moduleTypes" multiple collapse-tags>
                        <el-option v-for="(value, key) in moduleTypePojo" :key="key" :label="value" :value="key"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="请求方式">
                    <el-select size="mini" style="width:100%" clearable v-model="queryForm.methods" multiple collapse-tags>
                        <el-option v-for="(value, key) in methodPojo" :key="key" :label="value" :value="key"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="异常严重级别">
                    <el-select size="mini" style="width:100%" clearable v-model="queryForm.severityLevels" multiple collapse-tags>
                        <el-option v-for="(value, key) in levelPojo" :key="key" :label="value" :value="key"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="调用结果">
                    <el-select size="mini" style="width:100%" clearable v-model="queryForm.results" multiple collapse-tags>
                        <el-option v-for="(value, key) in resultPojo" :key="key" :label="value" :value="key"></el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="操作员">
                    <el-input size="mini" style="width:100%" v-model="queryForm.operateUser" />
                </el-form-item>
                <el-form-item label="访问日期">
                    <el-date-picker
                        style="width:100%"
                        size="mini"
                        v-model="queryForm.operateDate"
                        type="date"
                        value-format="yyyyMMdd"
                        placeholder="选择日期"
                    >
                    </el-date-picker>
                </el-form-item>
                <div class="info-seach-operate">
                    <el-button type="primary" v-authCode.show="B_0108" size="mini" @click="refreshInfo">查询</el-button>
                    <el-button type="primary" size="mini" @click="resetInfo">重置</el-button>
                    <el-button type="primary" v-authCode.show="B_0109" size="mini" @click="refreshInfo">刷新</el-button>
                    <el-button type="primary" size="mini" @click="layoutDialog = true">布局设置</el-button>
                </div>
            </el-form>
        </div>
        <div class="info-table">
            <RiskTableP
                ref="multipleTable"
                :tableData="tableData"
                :column="showFieldList"
                :tableConfig="tableConfig"
                :searchParams="queryForm"
                @page-change="queryData"
                v-loading="loading"
                :paging="paging"
                :key="tableKey"
            >
                <template #requestParam="scope">
                    <el-tooltip
                        v-if="scope.row.requestParam"
                        placement="top-start"
                        :ref="'dcPopover' + scope.row.serialNo"
                        trigger="hover"
                        popper-class="tips-popper"
                        :open-delay="300"
                        enterable
                    >
                        <div slot="content">
                            <span>{{ popKeyInfo.requestParam }}</span>
                        </div>
                        <span v-on:mouseover="getPopInfo(scope.row)"
                            ><span class="content">{{ scope.row.requestParam }}</span></span
                        >
                    </el-tooltip>
                    <span v-else>--</span>
                </template>

                <template #responseMsg="scope">
                    <el-tooltip
                        v-if="scope.row.responseMsg"
                        placement="top-start"
                        :ref="'dcPopover' + scope.row.serialNo"
                        trigger="hover"
                        popper-class="tips-popper"
                        :open-delay="300"
                        enterable
                    >
                        <div slot="content">
                            <span>{{ popKeyInfo.responseMsg }}</span>
                        </div>
                        <span v-on:mouseover="getPopInfo(scope.row)"
                            ><span class="content">{{ scope.row.responseMsg }}</span></span
                        >
                    </el-tooltip>
                    <span v-else>--</span>
                </template>

                <template #errorMsg="scope">
                    <!-- <el-popover
                        v-if="scope.row.errorMsg"
                        :ref="'dcPopover' + scope.row.serialNo"
                        trigger="hover"
                        popper-class="tips-popper"
                        :open-delay="300"
                        placement="top"
                        @show="getPopInfo(scope.row)"
                        @after-leave="hideSingle"
                    >
                        <span v-if="!popKeyInfo.requestParam">加载中...</span>
                        <span>{{ popKeyInfo.errorMsg }}</span>
                        <div slot="reference">
                            <span>{{ scope.row.errorMsg }}</span>
                        </div>
                    </el-popover> -->
                    <el-tooltip
                        v-if="scope.row.errorMsg"
                        placement="top-start"
                        :ref="'dcPopover' + scope.row.serialNo"
                        trigger="hover"
                        popper-class="tips-popper"
                        :open-delay="300"
                        enterable
                    >
                        <div slot="content">
                            <span>{{ popKeyInfo.errorMsg }}</span>
                        </div>
                        <span v-on:mouseover="getPopInfo(scope.row)"
                            ><span class="content">{{ scope.row.errorMsg }}</span></span
                        >
                    </el-tooltip>

                    <span v-else>--</span>
                </template>
            </RiskTableP>
        </div>

        <RiskTableLayout
            title="页面布局"
            :visible.sync="layoutDialog"
            :field-list="tableColumns"
            :selected-field-list="selectedFieldList"
            :fixed-field-list="fixedFieldList"
            :reset-no-selected-field-list="defaultSelectedFieldList"
            :table-name="tableName"
            @on-submit="onSubmit"
        />
    </div>
</template>
<script lang="ts">
import { Component, Vue, Watch } from 'vue-property-decorator';
import { paging, selects } from './info-data';
import { timeFormat, dateFormat, objToVxeFilterArr } from '@/utils/tools';
import RiskIconButton from '@/common/components/risk-icon-button.vue';
import XEUtils from 'xe-utils';
import { TableConfigVO } from '@/common/vo';
import RiskTableLayout from '@/common/components/risk-table-layout.vue';
import RiskTableP from '@/common/components/risk-table-plus.vue';
import moment from 'moment';

@Component({
    name: 'InfoList',
    components: {
        RiskIconButton,
        RiskTableP,
        RiskTableLayout,
    },
})
export default class InfoList extends Vue {
    private tableData: any = [];
    timeFormat = timeFormat;
    dateFormat = dateFormat;

    private loading: boolean = false;
    private paging: paging = {
        currentPage: 1,
        pageSize: 25,
        total: 0,
    };

    queryForm = {
        auths: [],
        browser: '',
        environment: '',
        errorMsg: '',
        host: '',
        methods: [],
        moduleTypes: [],
        operateDate: moment().format('YYYYMMDD'),
        operateRemark: '',
        operateTypes: [],
        operateUser: '',
        requestParam: '',
        requestUrl: '',
        responseMsg: '',
        results: ['失败'],
        sceneTypes: [],
        serialNo: '',
        severityLevels: [],
        sort: {
            field: '',
            order: '',
        },
        time: '',
    };

    // 操作类型下拉
    operateTypePojo = {
        '0': '人为请求',
        '1': '自动刷新请求',
        '2': '系统操作请求',
    };

    // 异常场景下拉
    sceneTypePojo = {
        '1': '初始化状态',
        '2': '基础数据同步(条目/动态维度)',
        '3': '服务执行状态',
        '4': '业务接口状态',
    };

    // 异常模块下拉
    moduleTypePojo = {
        // '0': '默认值', // 不显示
        '1': '初始化内存数据加载',
        '2': '初始化ETF外部数据加载',
        '3': '初始化数据转换过程加载',
        '4': '动态维度同步',
        '5': '条目同步',
        '6': '请求引擎接口',
        '7': '试算接口',
    };

    // 请求方式下拉
    methodPojo = {
        POST: 'POST',
        GET: 'GET',
        PUT: 'PUT',
        DELETE: 'DELETE',
    };

    // 严重级别下拉
    levelPojo = {
        '0': '信息',
        '1': '警告',
        '2': '错误',
        '3': '致命',
    };

    // 调用结果下拉
    resultPojo = {
        成功: '成功',
        失败: '失败',
    };

    // 日志表格列
    tableColumns: any[] = [
        { title: '序号', field: 'serialNo', minWidth: 120, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'left' },
        { title: '操作事件', field: 'operateRemark', minWidth: 120, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'center' },
        {
            title: '操作类型',
            field: 'operateTypes',
            minWidth: 120,
            sortable: true,
            filterType: 'funnel',
            filters: objToVxeFilterArr(this.operateTypePojo),
            align: 'center',
            render: (value, row) => this.operateTypePojo[row.operateType] || '--',
        },
        {
            title: '异常场景',
            field: 'sceneTypes',
            minWidth: 120,
            sortable: true,
            filterType: 'funnel',
            filters: objToVxeFilterArr(this.sceneTypePojo),
            align: 'center',
            render: (value, row) => this.sceneTypePojo[row.sceneType] || '--',
        },
        {
            title: '异常模块',
            field: 'moduleTypes',
            minWidth: 120,
            sortable: true,
            filterType: 'funnel',
            filters: objToVxeFilterArr(this.moduleTypePojo),
            align: 'center',
            render: (value, row) => this.moduleTypePojo[row.moduleType] || '--',
        },
        {
            title: '异常严重级别',
            field: 'severityLevels',
            minWidth: 150,
            sortable: true,
            filterType: 'funnel',
            filters: objToVxeFilterArr(this.levelPojo),
            align: 'center',
            render: (value, row) => this.levelPojo[row.severityLevel] || '--',
        },
        { title: '请求地址', field: 'requestUrl', minWidth: 120, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'left' },
        { title: '客户端环境', field: 'environment', minWidth: 140, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'left' },
        { title: '客户端地址', field: 'host', minWidth: 140, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'left' },
        { title: '浏览器', field: 'browser', minWidth: 120, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'left' },
        {
            title: '调用结果',
            field: 'results',
            minWidth: 120,
            sortable: true,
            filterType: 'funnel',
            filters: objToVxeFilterArr(this.resultPojo),
            align: 'center',
            style: (value, record) => {
                if (record.result === '成功') {
                    return { color: 'green' };
                }
                return { color: 'red' };
            },
            render: (value, row) => row.result || '--',
        },
        { title: '调用耗时(ms)', field: 'time', minWidth: 140, sortable: true, align: 'right' },
        {
            title: '请求方式',
            field: 'methods',
            minWidth: 120,
            sortable: true,
            filterType: 'funnel',
            filters: objToVxeFilterArr(this.methodPojo),
            align: 'center',
            render: (value, row) => row.method || '--',
        },
        { title: '请求参数', field: 'requestParam', minWidth: 120, sortable: true, align: 'left', notShowTooltip: true },
        { title: '返回信息', field: 'responseMsg', minWidth: 120, sortable: true, align: 'left', notShowTooltip: true },
        { title: '报错信息', field: 'errorMsg', minWidth: 120, sortable: true, align: 'left', notShowTooltip: true },
        {
            title: '是否经过认证',
            field: 'auths',
            minWidth: 160,
            sortable: true,
            filterType: 'funnel',
            filters: [
                { label: '是', value: true },
                { label: '否', value: false },
            ],
            align: 'center',
            render: (value, row) => (row.auth ? '是' : '否'),
        },
        { title: '操作员', field: 'operateUser', minWidth: 120, sortable: true, filterType: 'search', filters: [{ data: '' }], align: 'center' },
        {
            title: '访问时间',
            field: 'operateDate',
            minWidth: 150,
            sortable: true,
            render: (value, row) => dateFormat(row.operateDate) + ' ' + timeFormat(row.operateTime),
        },
    ];

    layoutDialog: boolean = false; // 布局设置loading
    // 默认显示表格列
    defaultSelectedFieldList: any[] = [];
    selectedFieldList: any[] = [];
    showFieldList: any[] = [];
    fixedFieldList: any[] = [
        {
            title: '序号',
            field: 'serialNo',
            id: 'serialNo',
            content: '序号',
            minWidth: 120,
            sortable: true,
            filterType: 'search',
            filters: [{ data: '' }],
            align: 'left',
        },
        {
            title: '报错信息',
            field: 'errorMsg',
            id: 'errorMsg',
            content: '报错信息',
            minWidth: 120,
            sortable: true,
            filterType: 'search',
            filters: [{ data: '' }],
            align: 'left',
        },
    ];
    tableName: string = 'INFO_LIST_TEST'; // 布局设置表名
    tableConfig: TableConfigVO = {
        rowKey: 'serialNo', // 主键key
        allRowKeys: [], // 所有页数据的key集合
    };

    tableKey: number = 0;
    sort = {
        field: '',
        order: '',
    };
    popInfoStorage: any = {}; // 证券集合仓库(枚举)
    popKeyInfo: any = {}; // 显示的浮窗数据

    created() {
        let tableColumns = [].concat(this.tableColumns);
        // 兼容布局设置组件
        tableColumns.map(item => {
            item.content = item.title;
            item.id = item.field;
        });
        // 布局设置默认列
        tableColumns.forEach(ele => {
            if (
                ['operateRemark', 'operateType', 'sceneType', 'moduleType', 'severityLevel', 'host', 'browser', 'operateUser', 'time'].includes(
                    ele.field
                )
            ) {
                this.defaultSelectedFieldList.push(ele);
            }
        });
        this.tableColumns = tableColumns;

        this.queryLayout();
        this.getSystemInfo(this.paging);
    }

    // 获取数据
    private getSystemInfo(paging: any): void {
        this.loading = true;
        this.$axios
            .post('/system/query/systemLog', {
                paging: paging,
                ...this.queryForm,
                operateDate: Number(this.queryForm.operateDate),
                sort: this.sort,
            })
            .then((res: any) => {
                this.loading = false;
                if (res) {
                    this.tableData = res.list;
                    this.paging.total = res.total;
                }
            })
            .catch(() => {
                this.loading = false;
            });
    }

    /**
     * 请求参数、返回信息、报错信息鼠标悬浮时调接口查询字段内容
     */
    getPopInfo(row: any) {
        const serialNo = row.serialNo;
        if (this.popInfoStorage[serialNo]) {
            this.popKeyInfo = this.popInfoStorage[serialNo];
            return;
        }
        this.$axios
            .post('/system/query/systemLog/' + serialNo)
            .then((res: any) => {
                this.popKeyInfo = res;
                this.popInfoStorage[serialNo] = res;
            })
            .catch(() => {});
    }

    /**
     * popover弹框隐藏
     */
    hideSingle() {
        setTimeout(() => {
            this.popKeyInfo = {};
        }, 50);
    }

    // 翻页
    private handleCurrentChange(val: number): void {
        this.paging.currentPage = val;
        this.getSystemInfo(this.paging);
    }

    private queryData(args: any) {
        if (args && args.type == 'sort') {
            this.sort.field = args['property'];
            this.sort.order = args['order'];
        }
        if (args && args.type == 'filter') {
            this.handleSetFilters();
        }
        this.getSystemInfo(this.paging);
    }

    // 刷新
    private refreshInfo(): void {
        this.handleSetFilters();
        this.getSystemInfo(this.paging);
    }

    // 重置
    private resetInfo(): void {
        this.queryForm.operateRemark = '';
        this.queryForm.operateTypes = [];
        this.queryForm.sceneTypes = [];
        this.queryForm.moduleTypes = [];
        this.queryForm.methods = [];
        this.queryForm.severityLevels = [];
        this.queryForm.results = ['失败'];
        this.queryForm.operateUser = '';
        this.queryForm.operateDate = moment().format('YYYYMMDD');
        this.handleSetFilters();
    }

    // 布局设置提交回调
    private async onSubmit(data) {
        await this.queryLayout();
        this.handleSetFilters();
    }

    /**
     *  设置表头筛选条件跟查询栏条件保持一致
     */
    handleSetFilters() {
        let fields = ['operateRemark', 'operateTypes', 'sceneTypes', 'moduleTypes', 'severityLevels', 'results', 'methods', 'operateUser', 'auths'];
        this.showFieldList.forEach(ele => {
            if (fields.includes(ele.field)) {
                const column = (this.$refs.multipleTable as any).$refs['xTable'].getColumnByField(ele.field);
                if (ele.field == 'operateRemark') {
                    console.log(column, 'column');
                }
                if (ele.filters) {
                    if (['operateTypes', 'sceneTypes', 'moduleTypes', 'severityLevels', 'results', 'methods', 'auths'].includes(ele.field)) {
                        const param = ele.field;
                        const option = column.filters;
                        if (this.queryForm[param] && this.queryForm[param].length) {
                            option.forEach(item => {
                                if (this.queryForm[param].includes(item.value)) {
                                    item.checked = true;
                                } else {
                                    item.checked = false;
                                }
                            });
                        } else {
                            option.forEach(item => {
                                item.checked = false;
                            });
                        }
                    } else {
                        const option = column.filters[0];
                        option.data = this.queryForm[ele.id];
                        if (this.queryForm[ele.id]) {
                            option.checked = true;
                        } else {
                            option.checked = false;
                        }
                    }
                }
            }
        });
        // 修改条件之后，需要手动调用 updateData 处理表格数据
        (this.$refs.multipleTable as any).$refs['xTable'].updateData();
    }

    /**
     * 查询页面布局信息
     */
    async queryLayout() {
        const resList: any = await new Promise((resolve, reject) => {
            this.$axios('/tableLayout/query/' + this.tableName)
                .then((res: any) => {
                    resolve(res);
                })
                .catch(err => {
                    reject(err);
                });
        });
        if (!resList) {
            // 新用户初始化
            const keys = this.defaultSelectedFieldList.map(item => item.field);
            this.showFieldList = this.tableColumns.filter(item => !keys.includes(item.field));
        } else {
            if (resList.length < 1) {
                // 选项为空
                this.showFieldList = this.fixedFieldList;
            } else {
                this.showFieldList = this.fixedFieldList.concat(JSON.parse(resList));
            }
        }
        const fixKeys = this.fixedFieldList.map(item => item.field);
        this.selectedFieldList = this.showFieldList.filter(item => !fixKeys.includes(item.field));

        // 表格列的render函数会丢失，需要重新赋值
        let columns = [];
        this.showFieldList.forEach(ele => {
            let index = this.tableColumns.findIndex(item => ele.id == item.id);
            if (index !== -1) {
                columns.push(this.tableColumns[index]);
            }
        });
        this.showFieldList = columns;
        this.tableKey++;
    }
}
</script>
<style lang="scss" scoped>
.info {
    padding-top: 10px;
    height: 100%;
    min-width: 1200px;
    .info-seach {
        padding: 8px 10px;
        border: 1px solid #eee;
        margin-bottom: 10px;
        .info-seach-form {
            display: grid;
            // grid-template-columns: repeat(5, minmax(255px, 20%));
            grid-template-columns: 19.5% 19.5% 19.5% 19.5% minmax(255px, 19.5%);
            justify-content: center;
            .el-form-item {
                margin-bottom: 10px;
                /deep/.el-form-item__label {
                    color: black;
                }
            }
        }
        .info-seach-operate {
            margin-top: 8px;
            text-align: right;
        }
        .el-button--mini,
        .el-button--mini.is-round {
            padding: 6px 5px !important;
        }
    }
    .info-table {
        height: calc(100vh - 150px);
    }
}
</style>
<style>
.tips-popper {
    height: fit-content;
    max-width: 700px;
    max-height: 300px;
    overflow: auto;
}
</style>
